﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FuncWorks.XNA.XTiled;
using Microsoft.Xna.Framework;
using fess.Screens;
using fess.RPG;
using Microsoft.Xna.Framework.Input;

namespace fess.Maps
{
  class Cemetery : GenericMap
  {
    int gamePhase = 0;
    bool foundFirst = false, sawObelisk = false, firstTime = true;
    Vector2 obelisk;
    public bool obeliskActive = true;

    public Cemetery(FessGame game)
      : base(game, game.Content.Load<Map>("cemetery"))
    {
      obelisk = map.ObjectLayers[0].MapObjects.FirstOrDefault(ob => ob.Name == "obelisk").Bounds.Center.ToVector2();
      drawObjects = true;
    }

    private List<MapObject> GetUndeads()
    {
      return map.ObjectLayers[0].MapObjects.Where(mo => mo.Type == "undead" && !mo.Properties.ContainsKey("used")).ToList();
    }

    public override void Activate()
    {
      game.fess.Character.Position = new Vector2(4, 6) * 32;
      base.Activate();

      if (firstTime)
      {
        firstTime = false;
        game.fess.Say("Обычная работа для Некроманта.\nЯ готовился к подобному весь год.", 5);
        activities.Add(new Timed(game.time + TimeSpan.FromMinutes(1), () =>
        {
          if (!foundFirst)
            game.fess.Say("Перед часовней стоит большое надгробие.\nЧем-то оно мне не нравится.\nПодойду-ка посмотрю поближе.");
        }));
      }
    }

    public override bool Update(GameTime gameTime)
    {
      if (!base.Update(gameTime))
        return false;

      if (foundFirst && !sawObelisk && 
        (game.CemeteryQuest == FessGame.CemeteryQuestStatus.Began || game.CemeteryQuest == FessGame.CemeteryQuestStatus.Undeads) &&
        (game.fess.Character.Position - obelisk).Length() < 200)
      {
        sawObelisk = true;
        game.fess.Say("Похоже, этот обелиск отталкивает Нежить.\nОтлично придумали местные маги.");
      }

      foreach (var obj in map.ObjectLayers["undead"].MapObjects)
        if (obj.Type == "undead" && !obj.Properties.ContainsKey("used"))
        {
          bool close = (obj.Bounds.Center.ToVector2() - game.fess.Character.Position).Length() < 100;
          if (obj.Name == "first" && gamePhase == 0 && close)
          {
            foundFirst = true;
            InvokeDropMessages();

            game.fess.Say("Ага, вот и наш клиент.");
            var undead = WakeUndead(obj);
            if (gamePhase == 0)
              undead.Death += FirstUndeadKilled;
          }
        }

      if (interaction == null && obeliskActive && (game.CemeteryQuest == FessGame.CemeteryQuestStatus.Done ||
        game.CemeteryQuest == FessGame.CemeteryQuestStatus.Reported) && game.turnUndead && (game.fess.Character.Position - obelisk).Length() < 70)
      {
        interaction = "Рассеять чары обелиска";

        if (Misc.IsKeyJustPressed(Keys.E))
        {
          game.fess.Say("А ведь я, пожалуй, могу нейтрализовать\nволшбу этого обелиска. Попробуем...");
          obeliskActive = false;
          game.fess.Say("Сработало. Теперь Нежить может\nздесь проходить. Мне это пригодится.", 10);
        }
      }

      if (interaction == null && game.turnUndead)
      {
        foreach(var u in GetUndeads())
          if ((u.Bounds.Center.ToVector2() - game.fess.Character.Position).Length() < 60)
          {
            interaction = "Побеспокоить умершего";
            if (Misc.IsKeyJustPressed(Keys.E))
              WakeUndead(u);

            break;
          }
      }

      return true;
    }

    protected override bool ExitEngaged(MapObject exit)
    {
      List<Answer> destinations = new List<Answer>();
      destinations.Add(new Answer("Домой", () => game.home.Activate()));
      destinations.Add(new Answer("Таверна", () => game.tavern.Activate()));
      if (game.CaveQuest != FessGame.CaveQuestStatus.Unknown)
        destinations.Add(new Answer("Пещера", () => game.caveOut.Activate()));

      game.AddActivity(new Dialog(game.fess,
          () => { },
          () => { },
        new Dialog.Line(game.fess, "Пора возвращаться.", destinations.ToArray())));

      return true;
    }

    public override Vector2 MoveObject(Vector2 from, Vector2 to, float radius, ActionCharacter self = null)
    {
      if (obeliskActive && self != null && self is Skeleton && (to - obelisk).Length() < 100 && (to - obelisk).Length() < (from - obelisk).Length())
        return from;

      return base.MoveObject(from, to, radius, self);
    }

    public int DestroyedUndeads
    {
      get
      {
        return (from c in characters
                where c.Dead && c is Skeleton && !((Skeleton)c).calmed
                select c).Count();
      }
    }

    void FirstUndeadKilled()
    {
      game.fess.Say("Хмм, моя магия побеспокоила ещё двоих.\nПокончу с ними и ухожу отсюда,\nпока они все не встали.");
      game.CemeteryQuest = FessGame.CemeteryQuestStatus.Undeads;

      gamePhase = 1;
      int secondWaveSize = 0;
      foreach (var obj in map.ObjectLayers["undead"].MapObjects)
        if (obj.Type == "undead" && obj.Name == "second")
        {
          var undead = WakeUndead(obj);
          ++secondWaveSize;

          undead.Death += () =>
          {
            --secondWaveSize;
            if (secondWaveSize == 0)
            {
              if (DestroyedUndeads > 1)
                WakeAll();
              else
              {
                game.fess.Say("Думаю, я неплохо справился.\nВернусь и отчитаюсь Даэнуру.");
                game.CemeteryQuest = FessGame.CemeteryQuestStatus.Done;
              }
            }
          };
        }
    }

    private void WakeAll()
    {
      int undeadLeft = 0;
      foreach (var obj in map.ObjectLayers["undead"].MapObjects)
        if (obj.Type == "undead" && !obj.Properties.ContainsKey("used"))
        {
          ++undeadLeft;
          var undead = WakeUndead(obj);
          undead.Death += () =>
          {
            --undeadLeft;
            if (undeadLeft == 0)
            {
              gamePhase = 4;
              drawObjects = true;
              game.fess.Say("Уфф. Смотритель кладбища будет вне себя.\nВернусь и расскажу всё Даэнуру.");
              game.CemeteryQuest = FessGame.CemeteryQuestStatus.Done;
            }
          };
        }

      game.fess.Say("Великая Тьма, во что я влип!");
      game.fess.Say("Так, спокойно.\nПридётся поработать по площадям.\nCебя самого бы не сжечь.", 10);
    }

    private ActionCharacter WakeUndead(MapObject obj)
    {
      obj.Properties["used"] = new Property();
      var skel = new Skeleton(game.fess.Level + (game.undeadBonus ? 1 : 0));
      var enemy = !game.undeadBonus;
      skel.hostile = enemy;
      AddCharacter(skel, obj.Bounds.Center.ToVector2(), enemy);
      skel.AddAI(new MeleeAI(skel, enemy));
      return skel;
    }
  }
}
